package cn.pangza.user.filter;

import cn.pangza.common.exception.BusinessException;
import cn.pangza.common.redis.service.RedisService;
import cn.pangza.common.utils.ResponseData;
import cn.pangza.common.utils.StringUtil;
import cn.pangza.user.constant.MessageConstant;
import cn.pangza.user.constant.UserRedisKeyConstant;
import cn.pangza.user.service.TokenService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class JwtFilter extends GenericFilter {

    @Autowired
    RedisService redisService;

    String[] WHITE_URL = new String[] {"/api/login", "/api/logout"};

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        response.setContentType("application/json;charset=utf-8");
        ObjectMapper objectMapper = new ObjectMapper();
        String url = request.getRequestURI();
        System.out.println("url = " + url);
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        try {
            if(antPathMatcher.match("/api/login", url)) {
                filterChain.doFilter(request, response);
                return;
            }
            List<String> collect = Arrays.stream(WHITE_URL).filter(item -> item.equals(url)).collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(collect)) {
                filterChain.doFilter(request, response);
                return;
            }
            String tokenKey = request.getHeader("Authorization");
            if(StringUtil.isEmpty(tokenKey)) {
                response.getWriter().write(objectMapper.writeValueAsString(ResponseData.tokenError(MessageConstant.NO_TOKEN)));
                return;
            }
            String token = redisService.get(UserRedisKeyConstant.USER_TOKEN + tokenKey);
            if(StringUtil.isEmpty(token)) {
                response.getWriter().write(objectMapper.writeValueAsString(ResponseData.tokenError(MessageConstant.NO_TOKEN)));
                return;
            }
            Authentication authentication = TokenService.checkToken(token);
            if(ObjectUtils.isEmpty(authentication)) {
                response.getWriter().write(objectMapper.writeValueAsString(ResponseData.tokenError(MessageConstant.NO_TOKEN)));
                return;
            }
            SecurityContextHolder.getContext().setAuthentication(authentication);
            filterChain.doFilter(request, response);
        } catch (BusinessException e) {
            response.getWriter().write(objectMapper.writeValueAsString(ResponseData.tokenError(MessageConstant.NO_TOKEN)));
        } finally {
            SecurityContextHolder.clearContext();
        }

    }
}
